<?php
namespace Core\Event\Application\Annotation;

use Core\Event\Annotation;
use Core\Exception;
use Phalcon\Validation;

class Input extends Annotation
{

    protected $_validation;

    //validate input params
    private function _validate($data, $arguments) {
        if(!is_array($arguments)) {
            return false;
        }
        foreach ($arguments as $key => $ruleValue) {
            if(!isset($data[$key])) {
                throw new \Exception("param {$key} is require");
                return false;
            }
            $inputValue = $data[$key];
            if(is_array($ruleValue)) {
                return $this->_validate($inputValue, $ruleValue);
            }else if ($ruleValue != ''){
                $verify = $this->verify($key, $inputValue, $ruleValue);
                if (!$verify){
                    throw new \Exception("param {$key} verify bad");
                }
            }
        }
        return true;
    }

    protected function verify($key, $value, $rules = '')
    {
        if (substr($rules, 0, 1) == '@'){
            if (preg_match_all('/([a-zA-Z]+\(.*?\))|([a-zA-Z]+)/', $rules, $result)){
                $result = $result[0];
                $rules = [];
                foreach($result AS $rule){
                    if (preg_match('/(.*?)\((.*?)\)/', $rule, $ruleRes)){
                        preg_match_all("/([a-zA-Z]+)='(.*?)'/", $ruleRes[2], $result);
                        $validator = '\Phalcon\Validation\Validator\\'.ucfirst($ruleRes[1]);
                        if (!class_exists($validator)){
                            throw new \Exception("Validator {$key}:{$ruleRes[1]} not found.");
                        }
                        $params = [];
                        foreach ($result[1] AS $index => $paramName){
                            $params[$paramName] = $result[2][$index];
                        }
                        $this->_validation->add($key, new $validator($params));
                        $rules[$ruleRes[1]] = $ruleRes[2];
                    }else{
                        $rules[$rule] = [];
                    }
                }
            }
            if (empty($value) && isset($rules['required'])){
                return false;
            }
        }else if($value != $rules){
            return false;
        }
        return true;
    }

    public function beforeHandleRequest($event)
    {
        $Arguments = $this->_annotation->getArguments();
        if (!is_array($Arguments)){
            return true;
        }
        if (array_keys($Arguments)[0] == '0'){
            $Arguments = $Arguments[0];
        }
        $params = $this->request->getParams();
        $this->_validation = new Validation();
        $bool = $this->_validate(
            $params,
            $Arguments
        );
        if(!$bool) {
            throw new Exception("Input params error.");
        }
        $message = $this->_validation->validate($params);
        if (count($message) > 0){
            throw new Exception($message[0]->getMessage());
        }
        return $bool;
    }
}